package com.seed.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.seed.core.configuration.AppConfiguration;
import com.seed.core.configuration.MicroConfiguration;
import com.seed.core.configuration.SeedConfiguration;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * nami.yml
 * nami
 *   micro1.yml
 *   micro1
 *     seed1.yml
 *     seed2.yml
 *     seed3.yml
 *     seed4.yml
 *   micro2.yml
 *   micro2
 *     seed1.yml
 *     seed2.yml
 *     seed3.yml
 *     seed4.yml
 *   seed1.yml
 *   seed2.yml
 *   seed3.yml
 *   seed4.yml
 */
public class AppLoadKit {

    /**
     * 加载应用配置
     * @param fileFullName 应用配置文件路径
     * @return 应用配置对象
     */
    public static AppConfiguration load(String fileFullName) {
        if(StrUtil.isBlank(fileFullName)) throw new RuntimeException("应用配置文件不能为空");

        return load(new File(fileFullName));
    }

    /**
     * 加载应用配置
     * @param appFile 应用配置文件
     * @return
     */
    public static AppConfiguration load(File appFile) {
        if(!appFile.exists()) throw new RuntimeException(String.format("配置文件【%s】不存在", appFile.getAbsolutePath()));

        String appMainName = FileUtil.mainName(appFile);
        AppConfiguration app = fileToObject(appFile, AppConfiguration.class);
        if(StrUtil.isBlank(app.getName())) app.setName(appMainName);

        File appFolder = new File(appFile.getParent() + File.separator + appMainName);
        if(!appFolder.exists()) return app;

        Map<String, SeedConfiguration> seeds = app.getSeeds();
        if(seeds == null) seeds = new HashMap<>();

        seeds.putAll(getSeeds(appFile));
        app.setSeeds(seeds);

        Map<String, MicroConfiguration> micros = app.getMicros();
        if(micros == null) micros = new HashMap<>();

        micros.putAll(getMicros(appFolder));
        app.setMicros(micros);

        return app;
    }

    private static Map<String, SeedConfiguration> getSeeds(File microFile) {
        Map<String, SeedConfiguration> ret = new HashMap<>();

        String mainName = FileUtil.mainName(microFile);
        File folder = new File(microFile.getParent() + File.separator + mainName);
        File[] files = folder.listFiles();
        if(files == null) return ret;

        for(File file: files) {
            if(!file.isFile()) continue;

            String seedName = StrKit.seedName(file.getName());
            SeedConfiguration seed = fileToObject(file, SeedConfiguration.class);
            ret.put(seedName, seed);
        }

        return ret;
    }

    private static Map<String, MicroConfiguration> getMicros(File appFolder) {
        Map<String, MicroConfiguration> ret = new HashMap<>();

        File microsFolder = new File(appFolder.getAbsolutePath() + File.separator + "micros");
        if(!microsFolder.exists()) return ret;

        File[] microFiles = microsFolder.listFiles();
        if(microFiles == null) return ret;

        for(File microFile: microFiles) {
            if(microFile.isDirectory()) continue;

            String microMainName = FileUtil.mainName(microFile);
            MicroConfiguration micro = fileToObject(microFile, MicroConfiguration.class);

            File microFolder = new File(microFile.getParent() + File.separator + microMainName);
            if(microFolder.exists()) {
                Map<String, SeedConfiguration> seeds = micro.getSeeds();
                if(seeds == null) seeds = new HashMap<>();

                seeds.putAll(getSeeds(microFile));
                micro.setSeeds(seeds);
            }
        }

        return ret;
    }

    private static <T> T fileToObject(File file, Class<T> clazz) {
        String suffix = FileUtil.getSuffix(file);
        if(StrUtil.isBlank(suffix)) throw new RuntimeException("不能识别文件类型");

        String content = FileUtil.readString(file, Charset.defaultCharset());
        if(suffix.equalsIgnoreCase("json")) return JSONUtil.toBean(content, clazz);
        if(suffix.equalsIgnoreCase("yml") || suffix.equalsIgnoreCase("yaml")) {
            return new Yaml().loadAs(content,clazz);
        }

        throw new RuntimeException(String.format("【%s】文件格式不支持，只支持【.json,.yml,.yaml】类型的文件", file.getAbsolutePath()));
    }
}
